package com.koudai.finance.service.impl;

import com.github.wxpay.sdk.WXPayUtil;
import com.google.common.collect.Maps;
import com.koudai.finance.constant.WebConfig;
import com.koudai.finance.dao.TradeDao;
import com.koudai.finance.entity.Trade;
import com.koudai.finance.service.CommonService;
import com.koudai.finance.service.PayService;
import com.koudai.finance.utils.*;
import com.koudai.finance.utils.wxpay.ResponseUtils;
import com.koudai.finance.utils.wxpay.WxPayUtils;
import com.koudai.finance.web.UserContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * @Description: 支付
 * @Author: ls
 * @Date: 2020/08/10 13:43
 */
@Slf4j
@Service
public class PayServiceImpl implements PayService {

    @Resource
    private TradeDao tradeDao;

    @Resource
    private WebConfig webConfig;

    @Resource
    private CommonService commonServiceImpl;

    /**
     * @Description: 付款接口
     * @Author: ls
     * @Date: 2020/08/10 13:44
     */
    @Override
    public Map<String, Object> createNative(HttpServletRequest request, String totalFee) throws Exception {
        Map<String, Object> resultMap = Maps.newHashMapWithExpectedSize(2);
        String notifyUrl = webConfig.getSysDomainName() + "/stock-api/pay/wxPayCallBack";
        Integer userId = UserContext.getUserId();
        String ip = IpUtil.getIpAddress(request);
        String totalFeeFen = AmountUtils.changeY2F(totalFee);
        String tradeNo = StringUtil.getRandomStr();
        String productId = "1";
        // 1、保存交易流水
        saveTransaction(userId, tradeNo, totalFeeFen);
        // 2、生成二维码
        Map<String, String> dataMap = WxPayUtils.wxNativePay(notifyUrl, tradeNo, totalFeeFen, ip, "购买物品费用", productId);
        String resultCode = dataMap.get("result_code");

        resultMap.put("codeUrl", dataMap.get("code_url"));
        resultMap.put("tradeNo", tradeNo);
        return resultMap;
    }

    /**
     * @Description: 保存交易信息
     * @Author: ls
     * @Date: 2020/08/10 14:09
     */
    private void saveTransaction(Integer userId, String tradeNo, String totalFee) {
        Integer id = tradeDao.checkIsExist(tradeNo);
        if (id == null) {
            Trade trade = Trade.builder().userId(userId).tradeNo(tradeNo).totalFee(Long.valueOf(totalFee)).payStatus(1).build();
            tradeDao.save(trade);
        }
    }

    /**
     * @Description: 支付回调通知
     * @Author: ls
     * @Date: 2020/08/10 14:09
     */
    @Override
    public void wxPayCallBack(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 1、获取request返回的值
        String retText = ResponseUtils.getRequestBody(request);
        Map<String, String> map = WXPayUtil.xmlToMap(retText);
        log.info("微信支付回调参数为:{}", map);
        // 2、检查签名信息
        String resultCode = map.get("result_code");
        StringBuilder sb = new StringBuilder();
        if (!StringUtils.equals("SUCCESS", resultCode)) {
            log.error("支付失败");
            sb.append("<xml>");
            sb.append("<return_code><![CDATA[FAIL]]></return_code>");
            sb.append("<return_msg><![CDATA[OK]]></return_msg>");
            sb.append("</xml>");
            ResponseUtils.response(response, sb.toString());
            return;
        }
        String tradeNo = map.get("out_trade_no");
        String totalFee = map.get("total_fee");
        String outTradeNo = map.get("transaction_id");
        // 3、处理支付后的逻辑
        dealTradeInfo(tradeNo, outTradeNo, totalFee);
        // 4、响应完成到微信
        sb.append("<xml>");
        sb.append("<return_code><![CDATA[SUCCESS]]></return_code>");
        sb.append("<return_msg><![CDATA[OK]]></return_msg>");
        sb.append("</xml>");
        ResponseUtils.response(response, sb.toString());
    }

    /**
     * @Description: 处理交易结果
     * @Author: ls
     * @Date: 2020/08/11 9:55
     */
    public void dealTradeInfo(String tradeNo, String outTradeNo, String totalFee) {
        // 1、对支付状态进行判断 防止重复处理
        Trade t = tradeDao.getTradeByTradeNo(tradeNo);
        if (t.getPayStatus() == 2) {
            return;
        }
        // 2、删除之前的未支付的订单记录
        tradeDao.delete(t.getUserId(), t.getTradeNo());
        // 3、更新交易支付状态
        Trade trade = Trade.builder().id(t.getId()).outTradeNo(outTradeNo).payStatus(2).build();
        tradeDao.update(trade);
        // 4、更新账户余额信息 2分钱一条目前
        long money = Long.parseLong(totalFee);
        long point;
        if (money % 2 == 0) {
            point = money / 2;
        } else {
            point = money / 2 + 1;
        }
    }

}